Išsami skirtingų kilmės šaltinių išteklių dalijimosi (CORS) ir parengiamųjų užklausų analizė. Sužinokite, kaip spręsti CORS problemas ir apsaugoti savo žiniatinklio programas pasaulinei auditorijai.
CORS demistifikavimas: išsami „JavaScript“ parengiamosios užklausos tvarkymo analizė
Nuolat besiplečiančiame žiniatinklio kūrimo pasaulyje saugumas yra svarbiausias dalykas. Skirtingų kilmės šaltinių išteklių dalijimasis (CORS) yra esminis saugumo mechanizmas, įdiegtas žiniatinklio naršyklėse, siekiant apriboti tinklalapių galimybę teikti užklausas į kitą domeną nei tas, iš kurio buvo pateiktas pats tinklalapis. Tai pagrindinė saugumo funkcija, skirta apsaugoti nuo kenkėjiškų svetainių prieigos prie jautrių duomenų. Šiame išsamiame vadove gilinsimės į CORS subtilybes, ypatingą dėmesį skirdami parengiamųjų užklausų tvarkymui. Išnagrinėsime CORS „kodėl“, „ką“ ir „kaip“, pateikdami praktinių pavyzdžių ir sprendimų dažniausiai pasitaikančioms problemoms, su kuriomis susiduria kūrėjai visame pasaulyje.
Tos pačios kilmės politikos supratimas
CORS pagrindas yra tos pačios kilmės politika (SOP). Ši politika yra naršyklės lygio saugumo mechanizmas, kuris apriboja viename kilmės šaltinyje veikiančių scenarijų prieigą prie išteklių iš kito kilmės šaltinio. Kilmės šaltinį apibrėžia protokolas (pvz., HTTP arba HTTPS), domenas (pvz., example.com) ir prievadas (pvz., 80 arba 443). Du URL adresai turi tą pačią kilmę, jei šie trys komponentai tiksliai sutampa.
Pavyzdžiui:
https://www.example.com/app1/index.htmlirhttps://www.example.com/app2/index.htmlturi tą pačią kilmę (tas pats protokolas, domenas ir prievadas).https://www.example.com/index.htmlirhttp://www.example.com/index.htmlturi skirtingas kilmes (skirtingi protokolai).https://www.example.com/index.htmlirhttps://api.example.com/index.htmlturi skirtingas kilmes (skirtingi subdomenai laikomi skirtingais domenais).https://www.example.com:8080/index.htmlirhttps://www.example.com/index.htmlturi skirtingas kilmes (skirtingi prievadai).
SOP skirta apsaugoti nuo kenkėjiškų scenarijų vienoje svetainėje prieigos prie jautrių duomenų, tokių kaip slapukai ar vartotojo autentifikavimo informacija, kitoje svetainėje. Nors SOP yra būtina saugumui, ji taip pat gali būti ribojanti, ypač kai reikalingos teisėtos skirtingų kilmės šaltinių užklausos.
Kas yra skirtingų kilmės šaltinių išteklių dalijimasis (CORS)?
CORS yra mechanizmas, leidžiantis serveriams nurodyti, kurie kilmės šaltiniai (domenai, schemos ar prievadai) gali pasiekti jų išteklius. Iš esmės tai sušvelnina SOP, leisdama kontroliuojamą prieigą iš skirtingų kilmės šaltinių. CORS įgyvendinamas naudojant HTTP antraštes, kuriomis keičiasi klientas (dažniausiai žiniatinklio naršyklė) ir serveris.
Kai naršyklė pateikia skirtingų kilmės šaltinių užklausą (t. y., užklausą į kitą kilmės šaltinį nei dabartinis puslapis), ji pirmiausia patikrina, ar serveris leidžia šią užklausą. Tai daroma išnagrinėjus Access-Control-Allow-Origin antraštę serverio atsakyme. Jei užklausos kilmės šaltinis yra nurodytas šioje antraštėje (arba jei antraštė nustatyta kaip *, leidžianti visus kilmės šaltinius), naršyklė leidžia užklausai tęstis. Priešingu atveju naršyklė blokuoja užklausą, neleisdama „JavaScript“ kodui pasiekti atsakymo duomenų.
Parengiamųjų užklausų vaidmuo
Tam tikrų tipų skirtingų kilmės šaltinių užklausoms naršyklė inicijuoja parengiamąją užklausą. Tai yra OPTIONS užklausa, siunčiama serveriui prieš faktinę užklausą. Parengiamosios užklausos tikslas – nustatyti, ar serveris yra pasirengęs priimti faktinę užklausą. Serveris atsako į parengiamąją užklausą pateikdamas informaciją apie leidžiamus metodus, antraštes ir kitus apribojimus.
Parengiamosios užklausos suaktyvinamos, kai skirtingų kilmės šaltinių užklausa atitinka bet kurią iš šių sąlygų:
- Užklausos metodas nėra
GET,HEADarbaPOST. - Užklausoje yra pasirinktinių antraščių (t. y., antraščių, kurios nėra automatiškai pridedamos naršyklės).
Content-Typeantraštė yra nustatyta kaip bet kas kita neiapplication/x-www-form-urlencoded,multipart/form-dataarbatext/plain.- Užklausoje naudojami
ReadableStreamobjektai turinyje.
Pavyzdžiui, PUT užklausa su Content-Type lygiu application/json suaktyvins parengiamąją užklausą, nes ji naudoja kitą metodą nei leidžiami ir potencialiai neleidžiamą turinio tipą.
Kodėl reikalingos parengiamosios užklausos?
Parengiamosios užklausos yra būtinos saugumui, nes jos suteikia serveriui galimybę atmesti potencialiai žalingas skirtingų kilmės šaltinių užklausas prieš joms įvykdant. Be parengiamųjų užklausų kenkėjiška svetainė galėtų siųsti savavališkas užklausas serveriui be aiškaus serverio sutikimo. Parengiamoji užklausa leidžia serveriui patvirtinti, kad užklausa yra priimtina, ir apsaugo nuo potencialiai žalingų operacijų.
Parengiamųjų užklausų tvarkymas serverio pusėje
Tinkamas parengiamųjų užklausų tvarkymas yra labai svarbus siekiant užtikrinti, kad jūsų žiniatinklio programa veiktų teisingai ir saugiai. Serveris turi atsakyti į OPTIONS užklausą su atitinkamomis CORS antraštėmis, nurodydamas, ar faktinė užklausa yra leidžiama.
Štai pagrindinių CORS antraščių, naudojamų parengiamuosiuose atsakymuose, apžvalga:
Access-Control-Allow-Origin: Ši antraštė nurodo kilmės šaltinį (-ius), kuriems leidžiama pasiekti išteklius. Ji gali būti nustatyta konkrečiam kilmės šaltiniui (pvz.,https://www.example.com) arba*, kad būtų leidžiami visi kilmės šaltiniai. Tačiau naudoti*paprastai nerekomenduojama dėl saugumo priežasčių, ypač jei serveris tvarko jautrius duomenis.Access-Control-Allow-Methods: Ši antraštė nurodo HTTP metodus, kurie yra leidžiami skirtingų kilmės šaltinių užklausai (pvz.,GET,POST,PUT,DELETE).Access-Control-Allow-Headers: Ši antraštė nurodo nestandartinių HTTP antraščių, kurios leidžiamos faktinėje užklausoje, sąrašą. Tai būtina, jei klientas siunčia pasirinktines antraštes, tokias kaipX-Custom-HeaderarAuthorization.Access-Control-Allow-Credentials: Ši antraštė nurodo, ar faktinėje užklausoje gali būti kredencialų, tokių kaip slapukai ar autorizacijos antraštės. Ji turi būti nustatyta kaiptrue, jei kliento pusės kodas siunčia kredencialus ir serveris turėtų juos priimti. Pastaba: kai ši antraštė nustatyta kaip `true`, `Access-Control-Allow-Origin` *negali* būti nustatyta kaip `*`. Privalote nurodyti konkretų kilmės šaltinį.Access-Control-Max-Age: Ši antraštė nurodo maksimalų laiką (sekundėmis), kurį naršyklė gali talpykloje saugoti parengiamąjį atsakymą. Tai gali padėti pagerinti našumą, sumažinant siunčiamų parengiamųjų užklausų skaičių.
Pavyzdys: Parengiamųjų užklausų tvarkymas Node.js su Express
Štai pavyzdys, kaip tvarkyti parengiamąsias užklausas Node.js programoje naudojant „Express“ karkasą:
const express = require('express');
const cors = require('cors');
const app = express();
// Įjungti CORS visiems kilmės šaltiniams (tik kūrimo tikslais!)
// Gamybinėje aplinkoje nurodykite leidžiamus kilmės šaltinius geresniam saugumui.
app.use(cors()); //arba app.use(cors({origin: 'https://www.example.com'}));
// Maršrutas OPTIONS užklausoms (parengiamosioms) tvarkyti
app.options('/data', cors()); // Įjungti CORS vienam maršrutui. Arba nurodykite kilmę: cors({origin: 'https://www.example.com'})
// Maršrutas GET užklausoms tvarkyti
app.get('/data', (req, res) => {
res.json({ message: 'Tai yra skirtingų kilmės šaltinių duomenys!' });
});
// Maršrutas parengiamajai ir post užklausai tvarkyti
app.options('/resource', cors()); // įjungti parengiamąją užklausą DELETE užklausai
app.delete('/resource', cors(), (req, res, next) => {
res.send('ištrinti išteklių')
})
const port = 3000;
app.listen(port, () => {
console.log(`Serveris klausosi prievado ${port}`);
});
Šiame pavyzdyje mes naudojame cors tarpinę programinę įrangą CORS užklausoms tvarkyti. Norint gauti detalesnį valdymą, CORS galima įjungti kiekvienam maršrutui atskirai. Pastaba: gamybinėje aplinkoje primygtinai rekomenduojama nurodyti leidžiamus kilmės šaltinius naudojant origin parinktį, užuot leidžiant visus kilmės šaltinius. Leidžiant visus kilmės šaltinius naudojant *, jūsų programa gali tapti pažeidžiama saugumo spragoms.
Pavyzdys: Parengiamųjų užklausų tvarkymas Python su Flask
Štai pavyzdys, kaip tvarkyti parengiamąsias užklausas Python programoje naudojant „Flask“ karkasą ir flask_cors plėtinį:
from flask import Flask, jsonify
from flask_cors import CORS, cross_origin
app = Flask(__name__)
CORS(app) # Įjungti CORS visiems maršrutams
@app.route('/data')
@cross_origin()
def get_data():
data = {"message": "Tai yra skirtingų kilmės šaltinių duomenys!"}
return jsonify(data)
if __name__ == '__main__':
app.run(debug=True)
Tai yra paprasčiausias naudojimo būdas. Kaip ir anksčiau, kilmės šaltinius galima apriboti. Išsamesnės informacijos ieškokite flask-cors dokumentacijoje.
Pavyzdys: Parengiamųjų užklausų tvarkymas Java su Spring Boot
Štai pavyzdys, kaip tvarkyti parengiamąsias užklausas Java programoje naudojant „Spring Boot“:
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.Bean;
import org.springframework.web.servlet.config.annotation.CorsRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
@SpringBootApplication
public class CorsApplication {
public static void main(String[] args) {
SpringApplication.run(CorsApplication.class, args);
}
@Bean
public WebMvcConfigurer corsConfigurer() {
return new WebMvcConfigurer() {
@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/data").allowedOrigins("http://localhost:8080");
}
};
}
}
Ir atitinkamas valdiklis:
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class DataController {
@GetMapping("/data")
public String getData() {
return "Tai yra skirtingų kilmės šaltinių duomenys!";
}
}
Dažniausios CORS problemos ir jų sprendimai
Nepaisant svarbos, CORS dažnai gali tapti kūrėjų nusivylimo šaltiniu. Štai keletas dažniausiai pasitaikančių CORS problemų ir jų sprendimų:
-
Klaida: „Užklaustame ištekliuje nėra 'Access-Control-Allow-Origin' antraštės.“
Ši klaida rodo, kad serveris savo atsakyme negrąžina
Access-Control-Allow-Originantraštės. Norėdami tai ištaisyti, įsitikinkite, kad serveris yra sukonfigūruotas įtraukti šią antraštę ir kad ji yra nustatyta teisingam kilmės šaltiniui arba*(jei tinka).Sprendimas: Sukonfigūruokite serverį, kad į savo atsakymą įtrauktų `Access-Control-Allow-Origin` antraštę, nustatydami ją į užklausiamos svetainės kilmės šaltinį arba `*`, kad būtų leidžiami visi kilmės šaltiniai (naudokite atsargiai).
-
Klaida: „Atsakymas į parengiamąją užklausą nepraeina prieigos kontrolės patikrinimo: užklausos antraštės laukas X-Custom-Header neleidžiamas pagal Access-Control-Allow-Headers parengiamajame atsakyme.“
Ši klaida rodo, kad serveris neleidžia pasirinktinės antraštės (šiame pavyzdyje
X-Custom-Header) skirtingų kilmės šaltinių užklausoje. Norėdami tai ištaisyti, įsitikinkite, kad serveris įtraukia šią antraštę įAccess-Control-Allow-Headersantraštę parengiamajame atsakyme.Sprendimas: Pridėkite pasirinktinę antraštę (pvz., `X-Custom-Header`) į `Access-Control-Allow-Headers` antraštę serverio parengiamajame atsakyme.
-
Klaida: „Kredencialų žyma yra 'true', tačiau 'Access-Control-Allow-Origin' antraštė yra '*'“
Kai
Access-Control-Allow-Credentialsantraštė nustatyta kaiptrue,Access-Control-Allow-Originantraštė turi būti nustatyta konkrečiam kilmės šaltiniui, o ne*. Taip yra todėl, kad leidžiant kredencialus iš visų kilmės šaltinių kiltų saugumo rizika.Sprendimas: Naudojant kredencialus, nustatykite `Access-Control-Allow-Origin` konkrečiam kilmės šaltiniui, o ne `*`.
-
Parengiamoji užklausa nėra siunčiama.
Dar kartą patikrinkite, ar jūsų „Javascript“ kode yra `credentials: 'include'` savybė. Taip pat patikrinkite, ar jūsų serveris leidžia `Access-Control-Allow-Credentials: true`.
-
Prieštaringos konfigūracijos tarp serverio ir kliento.
Atidžiai patikrinkite savo serverio CORS konfigūraciją kartu su kliento nustatymais. Neatitikimai (pvz., serveris leidžia tik GET užklausas, o klientas siunčia POST) sukels CORS klaidas.
CORS ir saugumo gerosios praktikos
Nors CORS leidžia kontroliuojamą prieigą iš skirtingų kilmės šaltinių, svarbu laikytis saugumo gerųjų praktikų, kad būtų išvengta pažeidžiamumų:
- Venkite naudoti
*Access-Control-Allow-Originantraštėje gamybinėje aplinkoje. Tai leidžia visiems kilmės šaltiniams pasiekti jūsų išteklius, o tai gali kelti saugumo riziką. Vietoj to nurodykite tikslius leidžiamus kilmės šaltinius. - Atidžiai apsvarstykite, kuriuos metodus ir antraštes leisti. Leiskite tik tuos metodus ir antraštes, kurie yra griežtai būtini jūsų programos teisingam veikimui.
- Įdiekite tinkamus autentifikavimo ir autorizavimo mechanizmus. CORS nepakeičia autentifikavimo ir autorizavimo. Užtikrinkite, kad jūsų API būtų apsaugotas tinkamomis saugumo priemonėmis.
- Patvirtinkite ir išvalykite visą vartotojo įvestį. Tai padeda išvengti tarpvietinio scenarijų vykdymo (XSS) atakų ir kitų pažeidžiamumų.
- Palaikykite savo serverio CORS konfigūraciją atnaujintą. Reguliariai peržiūrėkite ir atnaujinkite savo CORS konfigūraciją, kad ji atitiktų jūsų programos saugumo reikalavimus.
CORS skirtingose kūrimo aplinkose
CORS problemos gali pasireikšti skirtingai įvairiose kūrimo aplinkose ir technologijose. Štai kaip spręsti CORS problemas keliuose dažniausiuose scenarijuose:
Vietinės kūrimo aplinkos
Vietinio kūrimo metu CORS problemos gali būti ypač erzinančios. Naršyklės dažnai blokuoja užklausas iš jūsų vietinio kūrimo serverio (pvz., localhost:3000) į nuotolinį API. Keletas metodų gali palengvinti šią problemą:
- Naršyklės plėtiniai: Plėtiniai, tokie kaip „Allow CORS: Access-Control-Allow-Origin“, gali laikinai išjungti CORS apribojimus testavimo tikslais. Tačiau *niekada* nenaudokite jų gamybinėje aplinkoje.
- Tarpiniai serveriai (Proxy): Sukonfigūruokite tarpinį serverį, kuris persiunčia užklausas iš jūsų vietinio kūrimo serverio į nuotolinį API. Tai iš naršyklės perspektyvos efektyviai paverčia užklausas „tos pačios kilmės“. Tokie įrankiai kaip
http-proxy-middleware(skirtas Node.js) yra naudingi šiam tikslui. - Serverio CORS konfigūravimas: Net kūrimo metu yra gera praktika sukonfigūruoti savo API serverį, kad jis aiškiai leistų užklausas iš jūsų vietinio kūrimo kilmės šaltinio (pvz.,
http://localhost:3000). Tai imituoja realią CORS konfigūraciją ir padeda anksti aptikti problemas.
Serverless aplinkos (pvz., AWS Lambda, Google Cloud Functions)
Serverless funkcijos dažnai reikalauja kruopštaus CORS konfigūravimo. Daugelis serverless platformų teikia integruotą CORS palaikymą, tačiau svarbu jį teisingai sukonfigūruoti:
- Platformai būdingi nustatymai: Naudokite platformos integruotas CORS konfigūracijos parinktis. Pavyzdžiui, AWS Lambda leidžia nurodyti leidžiamus kilmės šaltinius, metodus ir antraštes tiesiogiai API Gateway nustatymuose.
- Tarpinė programinė įranga / Bibliotekos: Didesniam lankstumui galite naudoti tarpinę programinę įrangą ar bibliotekas CORS tvarkymui savo serverless funkcijos kode. Tai panašu į metodus, naudojamus tradicinėse serverių aplinkose (pvz., naudojant
corspaketą Node.js Lambda funkcijose). - Atsižvelkite į
OPTIONSmetodą: Užtikrinkite, kad jūsų serverless funkcija teisingai tvarkytųOPTIONSužklausas. Dažnai tai apima atskiro maršruto sukūrimą, kuris grąžina atitinkamas CORS antraštes.
Mobiliųjų programėlių kūrimas (pvz., React Native, Flutter)
CORS yra mažiau tiesioginė problema natyvioms mobiliesiems programėlėms (Android, iOS), nes jos paprastai netaiko tos pačios kilmės politikos taip, kaip žiniatinklio naršyklės. Tačiau CORS vis tiek gali būti aktualus, jei jūsų mobilioji programėlė naudoja žiniatinklio peržiūrą (web view) žiniatinklio turiniui rodyti arba jei naudojate karkasus, tokius kaip React Native ar Flutter, kurie naudoja „JavaScript“:
- Žiniatinklio peržiūros (Web Views): Jei jūsų mobilioji programėlė naudoja žiniatinklio peržiūrą žiniatinklio turiniui rodyti, taikomos tos pačios CORS taisyklės kaip ir žiniatinklio naršyklėje. Sukonfigūruokite savo serverį, kad leistų užklausas iš žiniatinklio turinio kilmės šaltinio.
- React Native / Flutter: Šie karkasai naudoja „JavaScript“ API užklausoms teikti. Nors natyvi aplinka gali tiesiogiai netaikyti CORS, pagrindiniai HTTP klientai (pvz.,
fetch) tam tikrose situacijose vis tiek gali elgtis panašiai kaip CORS. - Natyvūs HTTP klientai: Teikiant API užklausas tiesiogiai iš natyvaus kodo (pvz., naudojant OkHttp Android platformoje arba URLSession iOS platformoje), CORS paprastai nėra veiksnys. Tačiau vis tiek reikia atsižvelgti į saugumo gerasias praktikas, tokias kaip tinkamas autentifikavimas ir autorizavimas.
Pasauliniai aspektai konfigūruojant CORS
Konfigūruojant CORS pasauliniu mastu pasiekiamai programai, būtina atsižvelgti į tokius veiksnius kaip:
- Duomenų suverenumas: Kai kurių regionų taisyklės reikalauja, kad duomenys būtų laikomi tame regione. CORS gali būti susijęs su prieiga prie išteklių tarpvalstybiniu mastu, potencialiai pažeidžiant duomenų rezidavimo įstatymus.
- Regioninės saugumo politikos: Skirtingos šalys gali turėti skirtingas kibernetinio saugumo taisykles ir gaires, kurios daro įtaką tam, kaip turėtų būti įgyvendintas ir apsaugotas CORS.
- Turinio pristatymo tinklai (CDN): Užtikrinkite, kad jūsų CDN yra tinkamai sukonfigūruotas perduoti reikiamas CORS antraštes. Netinkamai sukonfigūruoti CDN gali pašalinti CORS antraštes, sukeldami netikėtas klaidas.
- Apkrovos balansavimo įrenginiai ir tarpiniai serveriai: Patikrinkite, ar bet kokie apkrovos balansavimo įrenginiai ar atvirkštiniai tarpiniai serveriai jūsų infrastruktūroje teisingai tvarko parengiamąsias užklausas ir perduoda CORS antraštes.
- Daugiakalbis palaikymas: Apsvarstykite, kaip CORS sąveikauja su jūsų programos internacionalizavimo (i18n) ir lokalizavimo (l10n) strategijomis. Užtikrinkite, kad CORS politikos būtų nuoseklios skirtingose jūsų programos kalbų versijose.
CORS testavimas ir derinimas
Efektyvus CORS testavimas ir derinimas yra gyvybiškai svarbus. Štai keletas metodų:
- Naršyklės kūrėjo įrankiai: Naršyklės kūrėjo konsolė yra jūsų pirmasis sustojimas. „Network“ (Tinklo) skirtukas parodys parengiamąsias užklausas ir atsakymus, atskleisdamas, ar CORS antraštės yra ir ar jos teisingai sukonfigūruotos.
- `curl` komandinės eilutės įrankis: Naudokite `curl -v -X OPTIONS
`, kad rankiniu būdu siųstumėte parengiamąsias užklausas ir patikrintumėte serverio atsakymo antraštes. - Internetiniai CORS tikrintuvai: Daugybė internetinių įrankių gali padėti patvirtinti jūsų CORS konfigūraciją. Tiesiog ieškokite „CORS checker“.
- Vienetų ir integracijos testai: Rašykite automatizuotus testus, kad patikrintumėte, ar jūsų CORS konfigūracija veikia kaip tikėtasi. Šie testai turėtų apimti tiek sėkmingas skirtingų kilmės šaltinių užklausas, tiek scenarijus, kai CORS turėtų blokuoti prieigą.
- Registravimas ir stebėjimas: Įdiekite registravimą, kad sektumėte su CORS susijusius įvykius, tokius kaip parengiamosios užklausos ir blokuotos užklausos. Stebėkite savo žurnalus, ieškodami įtartinos veiklos ar konfigūracijos klaidų.
Išvada
Skirtingų kilmės šaltinių išteklių dalijimasis (CORS) yra gyvybiškai svarbus saugumo mechanizmas, leidžiantis kontroliuojamą prieigą prie žiniatinklio išteklių iš skirtingų kilmės šaltinių. Suprasti, kaip veikia CORS, ypač parengiamosios užklausos, yra labai svarbu kuriant saugias ir patikimas žiniatinklio programas. Laikydamiesi šiame vadove aprašytų gerųjų praktikų, galite efektyviai spręsti CORS problemas ir apsaugoti savo programą nuo galimų pažeidžiamumų. Visada teikite pirmenybę saugumui ir atidžiai apsvarstykite savo CORS konfigūracijos pasekmes.
Žiniatinklio kūrimui tobulėjant, CORS ir toliau bus kritinis žiniatinklio saugumo aspektas. Būtina nuolat domėtis naujausiomis CORS gerosiomis praktikomis ir metodais, norint kurti saugias ir pasauliniu mastu pasiekiamas žiniatinklio programas.